﻿/*
 * Created by SharpDevelop.
 * User: lebeda
 * Date: 7.2.2014
 * Time: 11:14
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Drawing;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Diagnostics;
using System.Collections.Generic;
using ShellContextMenuHelper;
using simpleExplorer.menuProviderImpl;

using System.Runtime.InteropServices;

namespace simpleExplorer
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        private MenuItemProvider menuProvider;   
        
        private static readonly Dictionary<string, string> replayCode = new Dictionary<string, string>
        {
            { "Up", "{UP}" },
            { "Down", "{DOWN}" },
            { "Return", "{ENTER}" },
            { "Escape", "{ESCAPE}" }
        };
        
        public MainForm(MenuItem menuItem, Options options)
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();
            
            onTopToolStripMenuItem.Checked = options.onTop;
            this.TopMost = onTopToolStripMenuItem.Checked;
            
            closeAfterExecuteToolStripMenuItem.Checked = options.closeExec;
            closeOnLostFocusToolStripMenuItem.Checked = options.closeOnLost;
            
//            this.Top = Cursor.Position.X;
//            this.Left = Cursor.Position.Y;
            centerOnScreenToolStripMenuItem.Checked = options.centerScreen;
            if (centerOnScreenToolStripMenuItem.Checked) {
                this.StartPosition = FormStartPosition.CenterScreen;
            }
            
            setNewPath(menuItem);
            
        }
        
        private void setNewPath(MenuItem menuItem) {
            lstBox.Items.Clear();
            
            
            menuProvider = Tools.menuProviderFactory(menuItem);
            
            foreach (MenuItem lMenuItem in menuProvider.GetMenuItemList(edtFind.Text)) {
                string caption = lMenuItem.caption;
                // TODO - zajistit filtr
                if (!String.IsNullOrWhiteSpace(edtFind.Text)) {
                    string smallCaption = caption.ToLower();
                    string smallFind = edtFind.Text.ToLower();
                    if (smallCaption.Contains(smallFind)) {
                        lstBox.Items.Add(caption);
                    }
                } else {
                    lstBox.Items.Add(caption);
                }
            }
            
            int searchBoxHeight = (edtFind.Visible ? edtFind.Height : 0);
            
            int itemsHeight = searchBoxHeight + lstBox.Items.Count * lstBox.ItemHeight;
            this.ClientSize = new Size(this.ClientSize.Width, itemsHeight);

            int maxHeigth = Screen.FromControl(this).Bounds.Height;
            if (this.Height > maxHeigth) this.Height = maxHeigth;

            if ((this.Height + this.Top) > maxHeigth)
                this.Top = maxHeigth - this.Height;

            if (centerOnScreenToolStripMenuItem.Checked && (this.Height < maxHeigth)) {
                this.StartPosition = FormStartPosition.CenterScreen;
                this.Top = (maxHeigth / 2) - (this.Height /2);
            }
            
            if (!edtFind.Focused) {
                lstBox.Select();
            }
            
            if (String.IsNullOrEmpty(lstBox.Text) && (lstBox.Items.Count > 0)) {
                lstBox.SetSelected(0,true); // select first item
            }
        }


        
        
        private void LstBoxKeyPress(object sender, KeyPressEventArgs e)
        {
            
            if (Char.IsLetterOrDigit(e.KeyChar)) {
                edtFind.Text += e.KeyChar.ToString();
                edtFind.Visible = true;
                edtFind.Focus();
                edtFind.Select(0,0);
                edtFind.SelectionStart = edtFind.Text.Length;
            }
            
            if (e.KeyChar.Equals((char)System.Windows.Forms.Keys.Enter)) {
                
                executeItem(menuProvider.GetCommandByMenuItem(lstBox.Text));

            }
            
            if (e.KeyChar.Equals((char)System.Windows.Forms.Keys.Back)) {
                setNewPath(Tools.getMenuUp(menuProvider));
                edtFind.Text = "";
            }
            
            
            if (e.KeyChar.Equals((char)System.Windows.Forms.Keys.Escape)) {
                if (isCloseAfterExecute()) {
                    this.Close();
                }
            }
        }

        /// <summary>
        /// execute command
        /// </summary>
        void executeItem(MenuItem menuItem)
        {
            if (ItemTarget.menu.Equals(menuItem.itemTarget)) {
                setNewPath(menuItem);
                edtFind.Text = "";
            } else if (ItemTarget.item.Equals(menuItem.itemTarget)) {
                
                ProcessStartInfo startInfo = new ProcessStartInfo();

                ExecLog.writeOnExecute(menuItem.caption);               
                
                startInfo.FileName = menuItem.cmd;
                if (!String.IsNullOrWhiteSpace(menuItem.param)) {
                    startInfo.Arguments = menuItem.param;
                }
                if (!String.IsNullOrWhiteSpace(menuItem.directory)) {
                    startInfo.WorkingDirectory = menuItem.directory;
                }
                
                System.Diagnostics.Process.Start(startInfo);
                
                if (isCloseAfterExecute())
                    this.Close();
            } else {
                throw new InvalidDataException("cannot execute type " + menuItem.itemTarget + ".");
            }
        }
        
        void LstBoxMouseDown(object sender, MouseEventArgs e)
        {
            lstBox.SelectedIndex = lstBox.IndexFromPoint(e.X, e.Y);
            
            if (e.Button == MouseButtons.Right) {
                string file = menuProvider.GetCommandByMenuItem(lstBox.Text).cmd;
                if (File.Exists(file) || Directory.Exists(file)) {
                    Point point = this.PointToScreen(new Point(e.X, e.Y));
                    executeExplorerMenu(file, point);
                }
            }

        }
        
        void LstBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue.Equals((char)System.Windows.Forms.Keys.F2)) {
                string file = menuProvider.GetCommandByMenuItem(lstBox.Text).cmd;
                if (File.Exists(file) || Directory.Exists(file)) {
                    Point point = lstBox.PointToScreen(Point.Empty);
                    executeExplorerMenu(file, point);
                }
            }
            
            if (e.KeyValue.Equals((char)System.Windows.Forms.Keys.F9)) {
                this.contextMenuStrip.Show(this.lstBox, new Point(this.Top, this.Left));
            }
        }

        void executeExplorerMenu(string file, Point point)
        {
            if (File.Exists(file) || Directory.Exists(file)) {
                ShellContextMenu ctxMnu = new ShellContextMenu();
                FileInfo[] arrFI = new FileInfo[1];
                arrFI[0] = new FileInfo(file);
                Int32 result = ctxMnu.ShowContextMenu(arrFI, this.PointToScreen(point));
                if (isCloseAfterExecute() && (result == 0)) this.Close();
            }
        }
        
        private bool isCloseAfterExecute() {
            return closeAfterExecuteToolStripMenuItem.Checked;
        }
        
        void LstBoxMouseClick(object sender, MouseEventArgs e)
        {
            lstBox.SelectedIndex = lstBox.IndexFromPoint(e.X, e.Y);
            executeItem(menuProvider.GetCommandByMenuItem(lstBox.Text));
        }
        
        void MainFormActivated(object sender, EventArgs e)
        {
            setNewPath(menuProvider.GetSelfMenuCreateDefinition());
        }
        
        void LstBoxMouseMove(object sender, MouseEventArgs e)
        {
            lstBox.SelectedIndex = lstBox.IndexFromPoint(e.X, e.Y);
        }
        
        void LstBoxMouseEnter(object sender, EventArgs e)
        {
            this.Activate();
            this.BringToFront();
            SetForegroundWindow(this.Handle);
            setNewPath(menuProvider.GetSelfMenuCreateDefinition());
        }
        
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        
        void EdtFindTextChanged(object sender, EventArgs e)
        {
            setNewPath(menuProvider.GetSelfMenuCreateDefinition());
            
            if (String.IsNullOrWhiteSpace(edtFind.Text)) {
                edtFind.Visible = false;
                lstBox.Focus();
            } else {
                edtFind.Focus();
                edtFind.Select(0,0);
                edtFind.SelectionStart = edtFind.Text.Length;
            }
        }
        
        void EdtFindKeyDown(object sender, KeyEventArgs e)
        {
            if (!Char.IsLetterOrDigit((char)e.KeyValue)) {
                List<string> specKeys = getSpecKeysInFind();
                
                string keyCode = e.KeyCode.ToString();
                if (specKeys.Contains(keyCode)) {
                    lstBox.Select();
                    SendKeys.Send(replayCode[keyCode]);
                    e.Handled = e.SuppressKeyPress = true;
                }                                
            }
        }

        private List<string> getSpecKeysInFind()
        {
            List<string> specKeys = new List<string>();
            specKeys.Add("Up");
            specKeys.Add("Down");
            specKeys.Add("Return");
            specKeys.Add("Escape");
            return specKeys;
        }
        
        void OnTopToolStripMenuItemCheckedChanged(object sender, EventArgs e)
        {
            this.TopMost = onTopToolStripMenuItem.Checked;
        }
        
        void MainFormDeactivate(object sender, EventArgs e)
        {
            if (closeOnLostFocusToolStripMenuItem.Checked) {
                this.Close();
            }
        }
        
    }
}
